home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Info-Mac 4
/
Info_Mac IV CD-ROM (Pacific HiTech Inc.)(August 1994).iso
/
Development
/
Source
/
Telnet 2.6.1d1 4⁄26⁄94 Folder
/
source
/
ftp
/
ftpbin.c
< prev
next >
Wrap
Text File
|
1994-04-13
|
60KB
|
1,908 lines
/*
* User FTP
* 6/8/87
*****************************************************************
* NCSA Telnet for the Macintosh *
* *
* National Center for Supercomputing Applications *
* Software Development Group *
* 152 Computing Applications Building *
* 605 E. Springfield Ave. *
* Champaign, IL 61820 *
* *
* Copyright (c) 1986-1992, *
* Board of Trustees of the University of Illinois *
*****************************************************************
*/
#ifdef MPW
#pragma segment FTPClient
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include "TelnetHeader.h"
#include "wind.h"
#include "netevent.proto.h"
#include "InternalEvents.h"
#include "VSkeys.h"
#include "network.proto.h"
#include "mydnr.proto.h"
#include "bkgr.proto.h"
#include "maclook.proto.h"
#include "vsdata.h"
#include "vsinterf.proto.h"
#include "menuseg.proto.h"
#include "rsmac.proto.h"
#include "macbinary.h"
#include "macutil.proto.h"
#include "binsubs.proto.h"
#include "ftppi.h" /* list of commands, help strings */
#include "ftpbin.proto.h"
#include "parse.proto.h"
#include "maclook.proto.h"
#include "netevent.proto.h"
#include "debug.h"
#include "Connections.proto.h"
//#define DEBUG_FTPCLIENT
#ifdef DEBUG_FTPCLIENT
#define ftpclient_debug_print(x) putln(x)
#else
#define ftpclient_debug_print(x)
#endif
#define FASCII 0
#define FIMAGE 1 /* This is different than the definition
in bkgr.c */
#define FAMODE 0
#define FIMODE 1
//#define FMMODE 2 /* Mac Binary, when ready */
#define HFTP 21
#define SUCCESS 2
#define ERROR -1
#define NONE -2
#define ABORT -3
#define INCOMPLETE -4
#define AMBIGUOUS -5
#define HAVEDATA 4
#define BUFFERS 8000 /* size of buffer */
#define PATHLEN 256
#define READSIZE 128 /* how much to read */
#define HELPRESID 23229
long
filelen = 0, /* file transfer length */
start = 0L, /* timing var */
towrite = 0, /* file transfer pointer */
translen = 0, /* length of file transfered */
transtime;
short
xp = 0, /* general pointer */
ftpfh, /* file handle for ftp */
fcnt = 0, /* counter for ftpd */
ftpfilemode = 0, /* file open mode for transfer */
hash = 0, /* hash mark printing */
sendport = 1, /* to send ports or not */
verbose = 1, /* informative messages */
bell = 0, /* sound bell */
autologin = 1, /* login on connect */
prompt = 1, /* check on multiple commands */
glob = 1, /* expand wildcards */
slashflip = 1, /* change \ to / */
fromtty = 1; /* default input from tty */
char Template[256];
CInfoPBRec ClientDirectoryState;
static short ftpdata;
static char bellchar = {7};
static char backspace = {8};
static char poundsign = {'#'};
FILE* fromfp = NULL; /* file pointer for input */
MBFile* ftp_mbfp;
unsigned char
*captlist = 0L, *newfile = 0L, *transfile = 0L, /* name of file being sent/received */
*xs = 0L; /* response string */
unsigned short curftpprt = 0; /* port to use */
char response_data[20][4]; /* BYU 2.4.12 - first 4 characters of
each response */
unsigned char response_count[20]; /* BYU 2.4.12 - non-zero indicates
waiting for response */
extern short scrn;
extern WindRec *screens;
#define RCPSEGSIZE 512
#define O_RAW O_RDONLY
#define EOLCHAR 13
#define captlistsize 2001L
void FTPClientunload(void) {}
/* putstring: display string using vt100 emulation routines */
void putstring (short ftpscrn, char *string)
{
for (; *string; string++)
parse (&screens[ftpscrn], (unsigned char *) string, 1);
}
char *stpblkp (char *mystring)
{
/* Return pointer to first non blank in string */
short mycnt;
char *ptr;
mycnt = 0;
ptr = mystring;
while (((*ptr == ' ') || (*ptr == '\t')) && (mycnt < 256)) {
ptr++;
mycnt++;
}
return (ptr);
}
char *stptok (char *mystring, char *myword, short mylen, char *myterms)
{
/* Return pointer to first non blank in string */
short done, i;
char *p, *q;
p = stpblkp (mystring); /* skip leading blanks */
i = 0;
done = 0;
while (*(p + i) && (i <= mylen) && (done == 0)) {
q = myterms;
while ((*q) && (*q != *(p + i)))
q++;
if (!(*q)) {
*(myword + i) = *(p + i);
i++;
}
else
done = 1;
}
*(myword + i) = '\0';
q = p + i;
return (q);
}
short ftpopen(Str255 name)
{
OSErr myerr;
short myrefnum;
myerr = HOpen (TelInfo->FTPClientVRefNum, TelInfo->FTPClientDirID, name, fsRdWrPerm, &myrefnum);
return (myrefnum);
}
/* End of Macintosh Routines created at BYU, 1988 */
/* ftpgets - read a line from the keyboard
returns ABORT if aborted, non-zero on success */
char ftpgets (char *s, short lim, short echo)
//char *s; /* where to put the line */
//short lim, echo; /* max chars to read, echo? */
{
int count, i;
unsigned char c;
char *save;
Boolean gotOne; /* Did we get an event */
EventRecord myEvent; /* Event Record for this loop */
count = 0; /* none read */
save = s; /* beginning of line */
while (1) {
gotOne = WaitNextEvent (everyEvent, &myEvent, gApplicationPrefs->TimeSlice, 0L);
if ((myEvent.what == keyDown) || (myEvent.what == autoKey))
c = myEvent.message & charCodeMask;
else {
Stask (); /* BYU 2.4.15 */
DoNetEvents (); /* process event queue */
c = 0;
}
switch (c) { /* allow certain editing chars */
case 8: /* backspace */
if (count) {
if (echo) {
parse (&screens[scrn], &c, 1);
parse (&screens[scrn], (unsigned char *) " ", 1);
parse (&screens[scrn], &c, 1);
}
count--; /* one less character */
s--; /* move pointer backward */
}
break;
case 13: /* carriage return, = ok */
if (echo)
putstring (scrn, "\015\012"); /* newline */
*s = '\0'; /* terminate the string */
return (c); /* return ok */
break;
case 21: /* kill line */
for (i = 0; i < s - save; i++) { /* length of line */
if (echo) { /* erase */
parse (&screens[scrn], (unsigned char *) &backspace, 1);
parse (&screens[scrn], (unsigned char *) " ", 1);
parse (&screens[scrn], (unsigned char *) &backspace, 1);
}
}
s = save; /* reset line */
break;
case 0: /* do nothing */
break;
default: /* not special char */
if (c > 31 && c < 127) { /* printable */
if (echo)
parse (&screens[scrn], &c, 1); /* display */
*s++ = c; /* add to string */
count++; /* length of string */
}
else /* acts as eol */
return (c); /* value of special char */
if (count == lim) { /* to length limit */
*s = '\0'; /* terminate */
return (c);
}
break;
}
}
}
/************************************************************************/
/* captcon capture everything from a connection into the capture list return -1 on closed
connection, else 0, 1 if paused
/*********************************************************************** */
short captcon(short cnum, short mywindow)
{
short capturesize, cnt = 0;
unsigned char s[80]; /* temporary string */
/* if (fromtty && n_scrlck()) return(TRUE); /* if paused, nothing to do */
capturesize = screens[mywindow].capturesize;
do {
cnt = netread (cnum, &s[0], 64); /* get some from queue */
if ((cnt + capturesize) < captlistsize) {
BlockMove (&s[0], &captlist[capturesize], (long) cnt);
capturesize += cnt;
}
/* demux all packets */
} while ((cnt > 0) && ((cnt + capturesize) < captlistsize));
captlist[capturesize] = 0;
screens[mywindow].capturesize = capturesize;
return (cnt); /* 0 normally, -1 if connection closed */
}
/************************************************************************/
/* telnet filter telnet options on incoming data
/*********************************************************************** */
short telnet (int port, int cnt, unsigned char *s)
{
register int i, mylen, myport;
char printline[256]; /* line to display */
myport = WindByPort (port);
for (i = 0; i < cnt; i++) { /* put on screen */
if (*(s + i) & 128) { /* if over ASCII 128 */
sprintf (printline, " %d ", *(s + i)); /* show as number */
mylen = strlen (printline);
parse (&screens[myport], (unsigned char *) &printline[0], mylen);
}
else
parse (&screens[myport], (s + i), 1);
}
return (TRUE);
}
/************************************************************************/
/* dumpcon take everything from a connection and send it to the screen
return -1 on closed connection, else 0, 1 if paused
/*********************************************************************** */
int dumpcon (int cnum, int mywindow)
{ /* BYU 2.4.12 */
short i1, i2, cnt = 0, result = 0; /* BYU 2.4.12 */
unsigned char s1[64], s2[128]; /* temporary strings */
/* if (fromtty && n_scrlck()) return(TRUE); /* if paused, nothing to do */
do {
cnt = netread (cnum, &s1[0], 64); /* get some from queue */
/* Search the incoming data for status codes and newlines */
i1 = 0;
i2 = 0;
while (i1 < cnt) {
/* Check for 3 digit codes beginning with "5" at the beginning of each line. */
if (s1[i1] == '\012' || s1[i1] == '\015') { /* BYU 2.4.12 */
response_count[mywindow] = 0; /* BYU 2.4.12 */
}
else if (response_count[mywindow] < 4) { /* BYU 2.4.12 */
response_data[mywindow][response_count[mywindow]++] = s1[i1]; /* BYU 2.4.12 */
if (response_count[mywindow] == 4) { /* BYU 2.4.12 */
if (response_data[mywindow][0] == '5' && /* BYU 2.4.12 */
response_data[mywindow][1] >= '0' && /* BYU 2.4.12 */
response_data[mywindow][1] <= '9' && /* BYU 2.4.12 */
response_data[mywindow][2] == '0' && /* BYU 2.4.12 */
response_data[mywindow][2] <= '9' && /* BYU 2.4.12 */
response_data[mywindow][3] == ' ') /* BYU 2.4.12 */
result = -1; /* BYU 2.4.12 - Abort indicated by other
host */
}
}
/* If a "newline" is found then force a "carriage return" immediately. */
if ('\012' == (s2[i2++] = s1[i1++]))
s2[i2++] = '\015';
}
telnet (cnum, i2, &s2[0]); /* display on screen, etc. */
/* demux all packets */
} while (cnt > 0);
return (result); /* BYU 2.4.12 - 0 normally, -1 if
connection closed */
}
/************************************************************************/
/* getword: remove a word from a string. Things within quotes are assumed
to be one word. return TRUE on success, FALSE on end of string
/*********************************************************************** */
short getword (char *string, char *word)
{
char *p, *q;
int i = 0;
p = stpblkp (string); /* skip leading blanks */
if (!(*p)) { /* no words in string */
word[0] = '\0';
return (FALSE);
}
if (*p == '!') { /* ! is a word */
word[0] = *p;
word[1] = '\0';
strcpy (string, ++p);
return (TRUE);
}
if (*p == '\"') { /* word delimited by quotes */
while (p[++i] && p[i] != '\"')
word[i - 1] = p[i];
word[i - 1] = '\0';
if (!p[i])
ftpclient_debug_print ("Missing \". Assumed at end of string.");
else
i++;
q = p + i;
}
else
q = stptok (p, word, 50, " \t\015\012"); /* get word, max len 50 */
p = stpblkp (q); /* remove trailing blanks */
strcpy (string, p); /* remove extracted stuff */
return (TRUE);
}
/************************************************************************/
/* lowercase: convert a string to lowercase
/*********************************************************************** */
short lowercase(char *word)
{
short i;
for (i = 0; word[i] = tolower (word[i]); i++) ;
return (TRUE);
}
/************************************************************************/
/* finduniq: find name that is a unique prefix of one of the entries in a list.
Return position of the entry, NONE if none, AMBIGUOUS if more than one.
/*********************************************************************** */
int finduniq (unsigned char *name, int listsize)
{
int i, j = NONE, len;
unsigned char *p, cmdstring[256];
len = strlen ((char *) name);
for (i = 0; i < listsize; i++) {
GetIndString (cmdstring, FTPCOMMANDS, i + 1);
p = (unsigned char *) p2cstr (cmdstring);
if (!strncmp ((char *) name, (char *) cmdstring, len)) { /* prefix */
if (len == strlen ((char *) cmdstring))
return (i + 1); /* exact match */
if (j != NONE)
j = AMBIGUOUS; /* more than one match */
else
j = i + 1; /* note prefix found */
}
}
return (j); /* prefix */
}
/************************************************************************/
/* checkoredir: check for output redirection. If the command contains a >,
assume a filename follows and extract it. Remove the redirection from
the original command. Also change \ to / return TRUE if redirection
specified, FALSE otherwise
/*********************************************************************** */
Boolean checkoredir(char *command, char *filename, short slashflip)
{
short i;
filename[0] = '\0';
for (i = 0; (command[i] != '>'); i++) { /* process command part */
if (slashflip && command[i] == '\\')
command[i] = '/';
if (!command[i])
return (FALSE); /* no redirection */
}
getword (&command[i + 1], filename); /* get redirected filename */
command[i] = '\0';
return (TRUE);
}
/************************************************************************/
/* getnname: get next name from captured list names delimited by newlines - <CR> or <LF>
/*********************************************************************** */
Boolean getnname(char *string, char *word)
{
char *s;
s = string;
while ((*string == '\012') || (*string == '\015'))
string++; /* skip initial newlines */
if (!(*string))
return (FALSE); /* end of captlist */
while ((*string != '\012') && (*string != '\015') && (*string))
*(word++) = *(string++);
while ((*string == '\012') || (*string == '\015'))
string++; /* skip trailing newline */
*word = '\0';
strcpy (s, string);
return (TRUE);
}
/********************************************************************/
/* FTP PI Protocol interpreter for user interface commands Will permit any command to
be abbreviated uniquely. Recognizes commands, translates them to the protocol
commands to be sent to the other server, and uses userftpd, the daemon, to do data
transfers.
/*********************************************************************** */
short ftppi (char *command)
{
Boolean needanswer;
int cmdno, i, cmd_status;
char cmdname[20], word[PATHLEN], line[MAXFTP], answer[20], ofilename[PATHLEN];
unsigned char destname[50]; /* who to connect to */
char printline[256]; /* line to display */
Str255 scratchPstring;
if (captlist == 0) {
captlist = (unsigned char *) NewPtrClear ((long) captlistsize);
/* newfile = (unsigned char *) NewPtrClear( (long) PATHLEN); /* Pointer, no allocation
necessary */
transfile = (unsigned char *) NewPtrClear ((long) PATHLEN);
xs = (unsigned char *) NewPtrClear ((long) (BUFFERS + 10));
}
// Should check for not enough memory here!
/* Indicates waiting for response *//* BYU 2.4.12 */
response_count[scrn] = 0; /* BYU 2.4.12 */
/* get command number */
if (!getword (command, cmdname))
return (FALSE); /* get command name */
/* removes first word from command */
lowercase (cmdname);
cmdno = finduniq ((unsigned char *) cmdname, NCMDS); /* search cmdlist for prefix */
if (cmdno == AMBIGUOUS) { /* not unique abbreviation */
putstring (scrn, "?Ambiguous command\015\012");
return (FALSE);
}
if (cmdno == NONE) { /* not a prefix of any command */
putstring (scrn, "?Invalid command\015\012");
return (FALSE);
}
/* change \ to / and check if command output redirected */
if (cmdno != BANG) { /* don't alter shell escape */
if (cmdno != LLS) /* do not flip slashes for LLS */
checkoredir(command, ofilename, slashflip); /* check redirection, flip \ */
else
checkoredir(command, ofilename, FALSE); /* check redirection */
}
/* process commands */
switch (cmdno) {
case QMARK:
case HELP:
if (!command[0]) { /* no argument */
putstring (scrn, "Commands may be abbreviated:\015\012");
/* display command list */
printline[0] = '\0';
for (i = 2; i < NCMDS; i++) {
GetIndString (scratchPstring, FTPCOMMANDS, i + 1);
PtoCstr(scratchPstring);
sprintf (word, "%-16s", (char *)scratchPstring); /* get word from list */
strcat (printline, word); /* add to line */
if ((i - 2) % 5 == 4) { /* display line */
printline[79] = '\0';
putstring (scrn, printline);
putstring (scrn, "\015\012");
printline[0] = '\0';
}
}
if (i % 5 != 4) {
putstring (scrn, printline); /* last line */
putstring (scrn, "\015\012");
}
return (TRUE);
}
/* help for specific commands */
else {
while (getword (command, word)) { /* loop for all args */
i = finduniq ((unsigned char *) word, NCMDS); /* which command? */
if (i == AMBIGUOUS) /* non-unique command name */
sprintf (printline, "?Ambiguous help command %s", word);
else if (i == NONE) /* no such command */
sprintf (printline, "?Invalid help command %s", word);
else { /* display help string */
GetIndString (scratchPstring, HELPRESID, i);
PtoCstr(scratchPstring);
}
putstring (scrn, (char *)scratchPstring);
putstring (scrn, "\015\012");
}
return (TRUE);
}
break;
case BANG: /* shell escape */
return (TRUE);
case BELL:
if (getword (command, word)) { /* scan arg */
lowercase (word);
if (!strcmp (word, "off"))
bell = FALSE;
else if (!strcmp (word, "on"))
bell = TRUE;
else
bell = !bell;
}
else
bell = !bell;
if (bell)
ftpclient_debug_print ("Bell mode on.");
else
ftpclient_debug_print ("Bell mode off.");
return (TRUE);
case BYE:
case QUIT:
cmd_status = ftpdo (scrn, "QUIT", ofilename);
netclose (screens[scrn].port);
destroyport (scrn);
return (TRUE);
case DEBUG: /* turn on/off debugging, optional level */
if (TelInfo->debug) {
TelInfo->debug = 0;
ftpclient_debug_print ("Debug off");
}
else {
TelInfo->debug = 1;
ftpclient_debug_print ("Debug on");
}
return (TRUE);
case GLOB: /* wildcard expansion */
if (getword (command, word)) {
lowercase (word);
if (!strcmp (word, "off"))
glob = FALSE;
else if (!strcmp (word, "on"))
glob = TRUE;
else
glob = !glob;
}
else
glob = !glob;
if (glob)
ftpclient_debug_print ("Globbing on.");
else
ftpclient_debug_print ("Globbing off.");
return (TRUE);
case HASH: /* hash mark printing */
if (getword (command, word)) {
lowercase (word);
if (!strcmp (word, "off"))
hash = FALSE;
else if (!strcmp (word, "on"))
hash = TRUE;
else
hash = !hash;
}
else
hash = !hash;
if (hash)
ftpclient_debug_print ("Hash mark printing on (1024 bytes/hash mark).");
else
ftpclient_debug_print ("Hash printing off.");
return (TRUE);
case INTERACTIVE: /* prompting on multiple transfers */
prompt = TRUE;
putstring (scrn, "Interactive mode on.\015\012");
return (TRUE);
case LCD: /* change local directory */
if (*(stpblkp (command))) { /* BYU 2.4.17 - CD */
getword (command, word); /* BYU 2.4.17 */
if (ChangeDirectory(&(TelInfo->FTPClientDirID), &(TelInfo->FTPClientVRefNum), word)) /* BYU 2.4.17 */
putstring (scrn, "Unable to change directory\015\012");
}
PathNameFromDirID(TelInfo->FTPClientDirID, TelInfo->FTPClientVRefNum, scratchPstring);
PtoCstr(scratchPstring);
sprintf (printline, "Local directory now %s\015\012", (char *)scratchPstring);
putstring (scrn, printline);
return (TRUE);
case LDIR: /* local DIR */
case LLS:
putstring (scrn, "Directory ");
if (!(*(stpblkp (command)))) { /* null response ok */
PathNameFromDirID(TelInfo->FTPClientDirID, TelInfo->FTPClientVRefNum, scratchPstring);
PtoCstr(scratchPstring);
putstring (scrn, (char *)scratchPstring);
sprintf (line, "*");
}
else {
putstring(scrn, command);
sprintf (line, "%s", command);
}
putstring (scrn, "\015\012");
strcpy(Template, &line[0]);
if (NULL == (newfile = (unsigned char *) firstname (Template, TelInfo->FTPClientDirID, TelInfo->FTPClientVRefNum, &ClientDirectoryState))) {
putstring (scrn, "No files found\015\012");
}
else {
putstring (scrn, (char *) newfile);
putstring (scrn, "\015\012");
while (NULL != (newfile = (unsigned char *) nextname (Template, &ClientDirectoryState))) {
putstring (scrn, (char *) newfile);
putstring (scrn, "\015\012");
}
}
return (TRUE);
case NONINTERACTIVE: /* turn off interactive prompting */
prompt = FALSE;
ftpclient_debug_print ("Interactive mode off.");
return (TRUE);
case OPEN: /* open connection to host */
PresentOpenConnectionDialog(); /* Open a connection */
return (TRUE);
case PROMPT: /* interactive prompting */
if (getword (command, word)) {
lowercase (word);
if (!strcmp (word, "off"))
prompt = FALSE;
else if (!strcmp (word, "on"))
prompt = TRUE;
else
prompt = !prompt;
}
else
prompt = !prompt;
if (prompt)
ftpclient_debug_print ("Interactive mode on.");
else
ftpclient_debug_print ("Interactive mode off.");
return (TRUE);
case SENDPORT: /* send PORT commands for each transfer */
if (getword (command, word)) {
lowercase (word);
if (!strcmp (word, "off"))
sendport = FALSE;
else if (!strcmp (word, "on"))
sendport = TRUE;
else
sendport = !sendport;
}
else
sendport = !sendport;
if (sendport)
ftpclient_debug_print ("Use of PORT cmds on.");
else
ftpclient_debug_print ("Use of PORT cmds off.");
return (TRUE);
case SLASHFLIP: /* change \ to / */
if (getword (command, word)) {
lowercase (word);
if (!strcmp (word, "off"))
slashflip = FALSE;
else if (!strcmp (word, "on"))
slashflip = TRUE;
else
slashflip = !slashflip;
}
else
slashflip = !slashflip;
if (slashflip)
ftpclient_debug_print ("Slash translation on.");
else
ftpclient_debug_print ("Slash translation off.");
return (TRUE);
case STATUS: /* display status info */
sprintf (printline, "Connected to %s", destname);
ftpclient_debug_print (printline);
if (ftpfilemode == FASCII)
ftpclient_debug_print ("Transfer mode is ascii.");
else
ftpclient_debug_print ("Transfer mode is binary.");
if (bell)
ftpclient_debug_print ("Bell on.");
else
ftpclient_debug_print ("Bell off.");
if (TelInfo->debug) {
ftpclient_debug_print ("Debug on");
}
else
ftpclient_debug_print ("Debug off");
if (glob)
ftpclient_debug_print ("Filename globbing on.");
else
ftpclient_debug_print ("Filename globbing off.");
if (hash)
ftpclient_debug_print ("Hash-mark printing on.");
else
ftpclient_debug_print ("Hash-mark printing off.");
if (prompt)
ftpclient_debug_print ("Interactive prompting on.");
else
ftpclient_debug_print ("Interactive prompting off.");
if (sendport)
ftpclient_debug_print ("Sending of port commands on.");
else
ftpclient_debug_print ("Sending of PORT cmds off.");
if (slashflip)
ftpclient_debug_print ("Flipping \\ to / on.");
else
ftpclient_debug_print ("Flipping \\ to / off.");
if (verbose)
ftpclient_debug_print ("Verbose mode on.");
else
ftpclient_debug_print ("Verbose mode off.");
ftpclient_debug_print ("\012Remote status:");
cmd_status = ftpdo (scrn, "STAT", ofilename);
return (TRUE);
case VERBOSE: /* display informative messages */
if (getword (command, word)) {
lowercase (word);
if (!strcmp (word, "off"))
verbose = FALSE;
else if (!strcmp (word, "on"))
verbose = TRUE;
else
verbose = !verbose;
}
else
verbose = !verbose;
if (verbose)
ftpclient_debug_print ("Verbose mode on.");
else
ftpclient_debug_print ("Verbose mode off.");
return (TRUE);
default: /* The other commands valid only if
connected (we always are here) */
switch (cmdno) {
case ACCT: /* get file in binary mode */
while (!(*(stpblkp (command)))) {
putstring (scrn, "Acct: ");
if (ftpgets (command, 100, 1) == ABORT)
return (FALSE);
}
sprintf (line, "ACCT %s", command);
cmd_status = ftpdo (scrn, line, ofilename); /* get file */
return (TRUE);
case ASCII: /* transfer mode */
cmd_status = ftpdo (scrn, "TYPE A", ofilename);
return (TRUE);
case MACB: /* transfer mode */
if (TelInfo->MacBinary) {
TelInfo->MacBinary = 0;
cmd_status = ftpdo (scrn, "MACB D", ofilename);
}
else {
TelInfo->MacBinary = 1;
cmd_status = ftpdo (scrn, "MACB E", ofilename);
}
return (TRUE);
case BGET: /* get file in binary mode */
i = ftpfilemode; /* save current mode */
if (i == FASCII)
cmd_status = ftpdo (scrn, "TYPE I", ofilename);
while (!(*(stpblkp (command)))) {
putstring (scrn, "File: ");
if (ftpgets (command, 100, 1) == ABORT)
return (FALSE);
}
sprintf (line, "RETR %s", command);
cmd_status = ftpdo (scrn, line, ofilename); /* get file */
if (i == FASCII)
cmd_status = ftpdo (scrn, "TYPE A", ofilename); /* restore mode */
return (TRUE);
case BINARY: /* binary mode */
cmd_status = ftpdo (scrn, "TYPE I", ofilename);
return (TRUE);
case BPUT: /* put file in binary mode */
i = ftpfilemode;
if (i == FASCII)
cmd_status = ftpdo (scrn, "TYPE I", ofilename);
while (!(*(stpblkp (command)))) { /* if no arg */
putstring (scrn, "File: "); /* get from user */
if (ftpgets (command, 100, 1) == ABORT)
return (FALSE);
}
sprintf (line, "STOR %s", command);
cmd_status = ftpdo (scrn, line, ofilename);
if (i == FASCII)
cmd_status = ftpdo (scrn, "TYPE A", ofilename);
return (TRUE);
case CD: /* change remote directory */
while (!(*(stpblkp (command)))) { /* if no arg, get from user */
putstring (scrn, "To: ");
if (ftpgets (command, 100, 1) == ABORT)
return (FALSE); /* abort */
}
getword (command, word);
if (!strcmp (word, "..")) { /* special case */
cmd_status = ftpdo (scrn, "CDUP", ofilename);
if (cmd_status != ERROR)
return (TRUE); /* if CDUP understood */
#if 0
ftpclient_debug_print ("Trying again...");
cmd_status = ftpdo (scrn, "XCUP", ofilename); /* try alternative */
if (cmd_status != ERROR)
return (TRUE);
ftpclient_debug_print ("Trying again..."); /* else try usual CD */
#endif
}
sprintf (line, "CWD %s", word); /* try CWD */
cmd_status = ftpdo (scrn, line, ofilename);
if (cmd_status != ERROR)
return (TRUE);
#if 0
ftpclient_debug_print ("Trying again...");
sprintf (line, "XCWD %s", word); /* try XCWD */
cmd_status = ftpdo (scrn, line, ofilename);
#endif
return (TRUE);
case CLOSE: /* drop connection */
cmd_status = ftpdo (scrn, "QUIT", ofilename);
netclose (screens[scrn].port);
destroyport (scrn);
return (TRUE);
case DEL:
case RM:
getword (command, word);
while (!word[0]) { /* get arg from user */
putstring (scrn, "File: ");
if (ftpgets (word, 100, 1) == ABORT)
return (FALSE); /* abort */
}
if (prompt) { /* check interactively */
sprintf (printline, "Delete %s? ", word);
putstring (scrn, printline);
ftpgets (answer, 20, 1);
if (tolower (*(stpblkp (answer))) != 'y')
return (TRUE);
}
sprintf (line, "DELE %s", word);
cmd_status = ftpdo (scrn, line, ofilename);
return (TRUE);
case DIR: /* get list of remote files */
if (ftpfilemode == FIMAGE) {
cmd_status = ftpdo (scrn, "TYPE A", ofilename);
if (getword (command, word)) {
sprintf (line, "LIST %s", word);
}
else
sprintf (line, "LIST");
strcpy (screens[scrn].ftpbuf, line);
screens[scrn].clientflags = TYPE_I_ON_CLOSE;
screens[scrn].ftpstate = 3; /* Do "LIST" when "TYPE" is finished */
screens[scrn].ftpnext = 1;
}
else {
if (getword (command, word)) { /* Do DIR */
sprintf (line, "LIST %s", word);
cmd_status = ftpdo (scrn, line, ofilename);
}
else
cmd_status = ftpdo (scrn, "LIST", ofilename);
}
return (TRUE);
case GET:
case RECV: /* get remote file */
while (!(*(stpblkp (command)))) { /* if no arg */
putstring (scrn, "File: ");
if (ftpgets (command, 100, 1) == ABORT)
return (FALSE); /* abort */
}
sprintf (line, "RETR %s", command);
cmd_status = ftpdo (scrn, line, ofilename);
return (TRUE);
case LS: /* get remote file list - short */
if (ftpfilemode == FIMAGE) {
cmd_status = ftpdo (scrn, "TYPE A", ofilename);
if (getword (command, word)) {
sprintf (line, "NLST %s", word);
}
else
sprintf (line, "NLST");
strcpy (screens[scrn].ftpbuf, line);
screens[scrn].clientflags = TYPE_I_ON_CLOSE;
screens[scrn].ftpstate = 3; /* Do "NLST" when "TYPE" is finished */
screens[scrn].ftpnext = 1;
}
else {
if (getword (command, word)) {
sprintf (line, "NLST %s", word);
cmd_status = ftpdo (scrn, line, ofilename);
}
else
cmd_status = ftpdo (scrn, "NLST", ofilename);
}
return (TRUE);
case MDELETE:
while (!(*(stpblkp (command)))) { /* no arg */
putstring (scrn, "Files: ");
if (ftpgets (command, 100, 1) == ABORT)
return (FALSE); /* abort */
}
while (getword (command, word)) { /* for each arg */
if (glob) { /* wildcard expansion */
sprintf (line, "NLST %s", word);
screens[scrn].clientflags |= CAPTURE_DATA;
cmd_status = ftpdo (scrn, line, ofilename); /* put exapnsion in captlist */
}
else
strcpy ((char *) captlist, word); /* captlist has name(s) now */
while (getnname ((char *) captlist, word)) { /* for each name */
if (prompt) { /* check */
sprintf (printline, "mdelete %s? ", word);
putstring (scrn, printline);
if (ftpgets (answer, 20, 1) == ABORT) { /* abort */
command[0] = '\0'; /* no more processing */
break; /* quit immediately */
}
if (tolower (*(stpblkp (answer))) != 'y')
continue;
}
sprintf (line, "DELE %s", word); /* delete */
cmd_status = ftpdo (scrn, line, ofilename);
}
}
return (TRUE);
case MDIR: /* remote multiple DIR */
i = ftpfilemode; /* save mode */
if (i == FIMAGE)
cmd_status = ftpdo (scrn, "TYPE A", ofilename);
while (!(*(stpblkp (command)))) { /* no arg */
putstring (scrn, "Directories: ");
if (ftpgets (command, 100, 1) == ABORT)
return (FALSE); /* abort */
}
while (getword (command, word)) { /* for each arg */
if (glob) { /* expand wildcards */
sprintf (line, "NLST %s", word);
screens[scrn].clientflags |= CAPTURE_DATA;
cmd_status = ftpdo (scrn, line, ofilename);
}
else
strcpy ((char *) captlist, word);
while (getnname ((char *) captlist, word)) { /* for each name */
if (prompt) { /* check */
sprintf (printline, "mdir %s? ", word);
putstring (scrn, printline);
if (ftpgets (answer, 20, 1) == ABORT) { /* abort */
command[0] = '\0'; /* no more processing */
break; /* quit immediately */
}
if (tolower (*(stpblkp (answer))) != 'y')
continue;
}
sprintf (line, "LIST %s", word); /* DIR */
cmd_status = ftpdo (scrn, line, ofilename);
}
}
if (i == FIMAGE)
cmd_status = ftpdo (scrn, "TYPE I", ofilename);
return (TRUE);
case MGET: /* get multiple files */
getword (command, line);
while (!line[0]) { /* no arg */
putstring (scrn, "Files: ");
if (ftpgets (line, 100, 1) == ABORT)
return (FALSE); /* abort */
}
if (getword (line, word)) {
sprintf (command, "NLST %s", word);
screens[scrn].clientflags |= CAPTURE_DATA;
cmd_status = ftpdo (scrn, command, ofilename);
screens[scrn].clientflags |= MGET_STATE;
}
return (TRUE);
case MKDIR: /* create directory */
while (!(*(stpblkp (command)))) { /* no arg */
putstring (scrn, "Directory: ");
if (ftpgets (command, 100, 1) == ABORT)
return (FALSE); /* abort */
}
sprintf (line, "XMKD %s", command); /* try XMKD */
cmd_status = ftpdo (scrn, line, ofilename);
if (cmd_status != ERROR)
return (TRUE);
ftpclient_debug_print ("Trying again...");
sprintf (line, "MKD %s", command); /* else try MKD */
cmd_status = ftpdo (scrn, line, ofilename);
return (TRUE);
case MLS:
i = ftpfilemode;
if (i == FIMAGE)
cmd_status = ftpdo (scrn, "TYPE A", ofilename);
while (!(*(stpblkp (command)))) { /* no arg */
putstring (scrn, "Directories: ");
if (ftpgets (command, 100, 1) == ABORT)
return (FALSE); /* abort */
}
while (getword (command, word)) { /* for each arg */
if (glob) { /* exapnd wildcards */
sprintf (line, "NLST %s", word);
screens[scrn].clientflags |= CAPTURE_DATA;
cmd_status = ftpdo (scrn, line, ofilename);
}
else
strcpy ((char *) captlist, word);
while (getnname ((char *) captlist, word)) { /* for each name */
if (prompt) { /* check */
sprintf (printline, "mls %s? ", word);
putstring (scrn, printline);
if (ftpgets (answer, 20, 1) == ABORT) { /* abort */
command[0] = '\0'; /* no more processing */
break; /* quit immediately */
}
if (tolower (*(stpblkp (answer))) != 'y')
continue;
}
sprintf (line, "NLST %s", word); /* DIR */
cmd_status = ftpdo (scrn, line, ofilename);
}
}
if (i == FIMAGE)
cmd_status = ftpdo (scrn, "TYPE I", ofilename);
return (TRUE);
case MODE: /* set stream mode */
getword (command, word);
lowercase (word);
if (strncmp (word, "stream", strlen (word)))
ftpclient_debug_print ("We only support stream mode, sorry.");
else
ftpclient_debug_print ("Mode is stream.");
return (TRUE);
case MPUT: /* put multiple files */
getword (command, (char *) captlist);
while (!captlist[0]) { /* no arg */
putstring (scrn, "Files: ");
if (ftpgets ((char *) captlist, 100, 1) == ABORT)
return (FALSE); /* abort */
}
if (getword ((char *) captlist, (char *) transfile)) { /* for each arg */
newfile = NULL;
needanswer = TRUE;
while (needanswer) {
needanswer = FALSE;
if (glob) { /* local wildcard expansion */
if (newfile == NULL) { /* if no expansions yet */
strcpy(Template, (char *)transfile);
newfile = (unsigned char *) firstname (Template, TelInfo->FTPClientDirID, TelInfo->FTPClientVRefNum, &ClientDirectoryState); /* get first name */
if (newfile == NULL) { /* if no expansions */
sprintf (printline, "No match for %s", transfile);
ftpclient_debug_print (printline);
if (getword ((char *) captlist, (char *) transfile)) {
needanswer = TRUE;
}
}
}
else { /* not first name */
newfile = (unsigned char *) nextname (Template, &ClientDirectoryState); /* get next name */
if (newfile == NULL) { /* if no names, next arg */
if (getword ((char *) captlist, (char *) transfile)) {
needanswer = TRUE;
}
}
}
}
else
newfile = transfile; /* no expansion */
if (newfile != NULL) {
#if 1 /* When prompting is fixed switch to the
code below */
sprintf (command, "STOR \"%s\"", newfile); /* name may have spl chars */
cmd_status = ftpdo (scrn, command, ofilename);
screens[scrn].clientflags |= MPUT_STATE;
#else
if (prompt) { /* check */
sprintf (printline, "mput %s? ", newfile);
putstring (scrn, printline);
if (ftpgets (answer, 20, 1) == ABORT) { /* abort */
command[0] = '\0'; /* no more processing */
break;
}
else if (tolower (*(stpblkp (answer))) == 'y') {
sprintf (command, "STOR \"%s\"", newfile); /* name may have spl
chars */
cmd_status = ftpdo (scrn, command, ofilename);
screens[scrn].clientflags |= MPUT_STATE;
}
}
else {
sprintf (command, "STOR \"%s\"", newfile); /* name may have spl chars */
cmd_status = ftpdo (scrn, command, ofilename);
screens[scrn].clientflags |= MPUT_STATE;
}
#endif
}
}
}
return (TRUE);
case PUT:
case SEND: /* put file */
while (!(*(stpblkp (command)))) { /* no args */
putstring (scrn, "File: ");
if (ftpgets (command, 100, 1) == ABORT)
return (FALSE);
}
sprintf (line, "STOR %s", command); /* put file */
cmd_status = ftpdo (scrn, line, ofilename);
return (TRUE);
case PWD:
#if 0
cmd_status = ftpdo (scrn, "XPWD", ofilename); /* try XPWD */
if (i != ERROR)
return (TRUE);
ftpclient_debug_print ("Trying again...");
#endif
cmd_status = ftpdo (scrn, "PWD", ofilename); /* else try PWD */
return (TRUE);
case QUOTE:
while (!(*(stpblkp (command)))) { /* no arg */
putstring (scrn, "Command: ");
if (ftpgets (command, 100, 1) == ABORT)
return (FALSE);
}
cmd_status = ftpdo (scrn, command, ofilename); /* send command */
return (TRUE);
case REMOTEHELP: /* get help */
if (*(stpblkp (command))) { /* for specific command */
sprintf (line, "HELP %s", command);
cmd_status = ftpdo (scrn, line, ofilename);
}
else
cmd_status = ftpdo (scrn, "HELP", ofilename); /* generic help */
return (TRUE);
case RENAME: /* rename remote file */
while (!(*(stpblkp (command)))) { /* no arg */
putstring (scrn, "From: ");
if (ftpgets (command, 100, 1) == ABORT)
return (FALSE);
}
getword (command, word);
sprintf (line, "RNFR %s", word);
cmd_status = ftpdo (scrn, line, ofilename); /* send rename from name */
while (!(*(stpblkp (command)))) { /* no second arg */
putstring (scrn, "To: ");
if (ftpgets (command, 100, 1) == ABORT) {
cmd_status = ftpdo (scrn, "ABOR", ofilename);
return (FALSE);
}
}
sprintf (line, "RNTO %s", command); /* send rename to name */
cmd_status = ftpdo (scrn, line, ofilename);
return (TRUE);
case RMDIR: /* remove remote dir */
while (!(*(stpblkp (command)))) { /* no arg */
putstring (scrn, "Directory: ");
if (ftpgets (command, 100, 1) == ABORT)
return (FALSE);
}
sprintf (line, "XRMD %s", command); /* try XRMD */
cmd_status = ftpdo (scrn, line, ofilename);
if (cmd_status != ERROR)
return (TRUE);
ftpclient_debug_print ("Trying again...");
sprintf (line, "RMD %s", command); /* try RMD */
cmd_status = ftpdo (scrn, line, ofilename);
return (TRUE);
case STRUCT: /* set structure type - only file */
getword (command, word);
lowercase (word);
if (strncmp (word, "file", strlen (word)))
ftpclient_debug_print ("We only support file structure, sorry.");
else
ftpclient_debug_print ("Structure is file.");
return (TRUE);
case TYPE: /* set transfer type */
if (!getword (command, word)) { /* no arg, just show */
if (ftpfilemode == FASCII)
ftpclient_debug_print ("Transfer type is ascii.");
else
ftpclient_debug_print ("Transfer type is binary.");
}
lowercase (word);
if (!strncmp (word, "ascii", strlen (word)))
cmd_status = ftpdo (scrn, "TYPE A", ofilename);
else if (!strncmp (word, "binary", strlen (word)) ||
!strncmp (word, "image", strlen (word)))
cmd_status = ftpdo (scrn, "TYPE I", ofilename);
else {
sprintf (printline, "Unrecognized type: %s", word);
ftpclient_debug_print (printline);
}
return (TRUE);
case USER: /* login to remote machine */
if (!(*(stpblkp (command)))) { /* null response to prompt ok */
putstring (scrn, "Username: ");
if (ftpgets (command, 100, 1) == ABORT)
return (FALSE);
}
sprintf (line, "USER %s", command); /* username */
if ((cmd_status = ftpdo (scrn, line, ofilename)) == TRUE)
return (TRUE);
#if 0
putstring (scrn, "Password: ");
#endif
if (ftpgets (word, PATHLEN, 0) == ABORT)
return (FALSE); /* no echoing */
sprintf (line, "PASS %s", word); /* password */
if ((cmd_status = ftpdo (scrn, line, ofilename)) == INCOMPLETE) { /* if account needed */
do {
putstring (scrn, "Account: ");
if (ftpgets (command, 100, 1) == ABORT)
return (FALSE);
} while (!(*(stpblkp (command))));
sprintf (line, "ACCT %s", command);
cmd_status = ftpdo (scrn, line, ofilename);
}
return (TRUE);
default: /* unknown command */
putstring (scrn, "?Invalid command\015\012");
#if 0
sprintf (printline, "***Unknown command no: %d", cmdno);
ftpclient_debug_print (printline);
#endif
break;
}
}
}
/************************************************************************/
/* ftpport return a new port number so that we don't try to re-use ports before the
mandatory TCP timeout period. (lifetime of a packet) use a time-based initial port
selection scheme.
/*********************************************************************** */
short ftpport(int ftpscrn)
{
unsigned int i;
unsigned char hostnum[5];
char sendline[60]; /* for port command */
if (!sendport) /* default port */
return (HFTP - 1);
if (curftpprt < 40000) { /* restart cycle */
i = (unsigned int) TickCount ();
curftpprt = 40000 + (i & 0x3fff);
}
i = curftpprt--; /* get port, update for next time */
netgetip (hostnum); /* get my ip number */
ftpdata = netlisten (i);
screens[ftpscrn].ftpport = ftpdata;
SetPortType(ftpdata, UDATA);
sprintf (sendline, "PORT %d,%d,%d,%d,%d,%d\015\012", hostnum[0], hostnum[1], hostnum[2],
hostnum[3], i / 256, i & 255); /* full port number */
netpush (screens[ftpscrn].port); /* empty command connection */
netwrite (screens[ftpscrn].port, sendline, strlen (sendline)); /* send PORT command */
return (i); /* port number */
}
/************************************************************************/
/* ftpdo Do whatever command is sent from the user interface using userftpd,
the background file handler
/*********************************************************************** */
int ftpdo (int ftpscrn, char *s, char *ofile)
{
int i;
char name[MAXFTP], name2[MAXFTP];
char commandbuf[MAXFTP];
HFileParam iop;
strcpy (commandbuf, s);
for (i = 0; i < 4; i++) {
commandbuf[i] = toupper (commandbuf[i]); /* command to upper case */
}
if (!strncmp (commandbuf, "STOR", 4)) { /* put file */
getword (&commandbuf[5], name); /* first arg - local file */
if (!commandbuf[5])
strcpy (&commandbuf[5], name); /* if only one argument */
else {
getword (&commandbuf[5], name2); /* second arg - removes quotes etc. */
strcpy (&commandbuf[5], name2); /* copy back into command */
}
ftp_mbfp = MBopen (&name[0], TelInfo->FTPClientVRefNum, TelInfo->FTPClientDirID,
MB_READ + /* BYU 2.4.18 */
( ((!TelInfo->MacBinary) || (ftpfilemode == FAMODE)) ? MB_DISABLE : 0) +
((ftpfilemode == FAMODE) ? MB_ISASCII : 0)
);
if (ftp_mbfp == 0L) {
putstring (ftpscrn, "Could not open file\015\012");
return (-1);
}
ftpfh = 12;
c2pstr (&name[0]);
GetFileInfo (TelInfo->FTPClientVRefNum, TelInfo->FTPClientDirID, (StringPtr)&name[0], &iop);
filelen = iop.ioFlLgLen;
if (TelInfo->MacBinary && (ftpfilemode == FIMODE))
filelen += iop.ioFlRLgLen;
ftpport (ftpscrn); /* open data connection */
screens[ftpscrn].ftpstate = 2;
screens[ftpscrn].ftpnext = 20;
strcpy (screens[ftpscrn].ftpbuf, commandbuf);
strcat (screens[ftpscrn].ftpbuf, "\015\012");
return (1);
}
else if (!strncmp (commandbuf, "RETR", 4)) { /* get file */
getword (&commandbuf[5], name); /* remote file */
if (commandbuf[5]) { /* two args present */
getword (&commandbuf[5], name2); /* local file */
if ((ftp_mbfp = MBopen (&name2[0], TelInfo->FTPClientVRefNum, TelInfo->FTPClientDirID, MB_WRITE + /* BYU 2.4.18 */
(((!TelInfo->MacBinary) || (ftpfilemode == FAMODE)) ? MB_DISABLE : 0) +
((ftpfilemode == FAMODE) ? MB_ISASCII : 0)
)) == 0L) {
putstring (ftpscrn, "Cannot open file to receive\015\012");
return (-1);
}
else
ftpfh = 12;
}
else {
if ((ftp_mbfp = MBopen (&name[0], TelInfo->FTPClientVRefNum, TelInfo->FTPClientDirID, MB_WRITE + /* BYU 2.4.18 */
(((!TelInfo->MacBinary) || (ftpfilemode == FAMODE)) ? MB_DISABLE : 0)
+ ((ftpfilemode == FAMODE) ? MB_ISASCII : 0)
)) == 0L) {
putstring (ftpscrn, "Cannot open file to receive\015\012");
return (-1);
}
else
ftpfh = 12;
}
strcpy (&commandbuf[5], name); /* Put remote name back into command */
ftpport (ftpscrn); /* open data connection */
screens[ftpscrn].ftpstate = 2;
screens[ftpscrn].ftpnext = 30;
strcpy (screens[ftpscrn].ftpbuf, commandbuf);
strcat (screens[ftpscrn].ftpbuf, "\015\012");
return (1);
}
else if (!strncmp (commandbuf, "LIST", 4) || !strncmp (commandbuf, "NLST", 4)) {
if ((screens[ftpscrn].clientflags & CAPTURE_DATA) != 0)
screens[ftpscrn].capturesize = 0; /* Size of captured data */
ftpport (ftpscrn); /* data connection */
screens[ftpscrn].ftpstate = 2;
screens[ftpscrn].ftpnext = 40;
strcpy (screens[ftpscrn].ftpbuf, commandbuf);
strcat (screens[ftpscrn].ftpbuf, "\015\012");
return (1);
}
else if (!strncmp (commandbuf, "TYPE", 4)) {
if (toupper (commandbuf[5]) == 'I')
ftpfilemode = FIMAGE; /* Remember mode */
else if (toupper (commandbuf[5]) == 'A')
ftpfilemode = FASCII;
}
netpush (screens[ftpscrn].port);
strcat (commandbuf, "\015\012"); /* BYU 2.4.11 */
netwrite (screens[ftpscrn].port, commandbuf, strlen (commandbuf)); /* BYU 2.4.11 - send
command */
c2pstr(ofile);
if (((screens[ftpscrn].clientflags & CAPTURE_DATA) == 0) && ofile[0]) { /* command redirected */
if ((screens[ftpscrn].ftpstate != 20) && (screens[ftpscrn].ftpstate != 30)) { /* not get or put */
if (0 > (ftpfh = ftpopen ((StringPtr)ofile)))
ftpclient_debug_print (" Cannot open output file.");
else if (ftpdata > -1) {
screens[ftpscrn].ftpstate = 30; /* act as get, since data goes into file */
}
else {
/* Close(ftpfh); /* BYU LSC */
ftpfh = 0;
}
}
}
return (FALSE);
}
/************************************************************************/
/* userftpd FTP receive and send file functions
/*********************************************************************** */
short userftpd (int code, int myport)
{
Boolean needanswer;
long mytime;
int cmd_status, connection_status, ftpstate, i, mycode, myftpdata, mytelport, mywindow;
char command[MAXFTP], printline[MAXFTP], word[MAXFTP];
mycode = code;
connection_status = 0; /* BYU 2.4.12 - assume good connection
status */
ftpstate = 1;
mywindow = WindByPort (myport);
if (mywindow >= 0) {
if (myport == screens[mywindow].port) {
ftpstate = screens[mywindow].ftpstate;
myftpdata = -1;
}
else {
ftpstate = screens[mywindow].ftpstate;
myftpdata = screens[mywindow].ftpport;
}
}
if (mywindow < 0)
return (0);
mytelport = screens[mywindow].port;
switch (ftpstate) {
default: /* unknown */
break;
case 1:
if ((mycode == CONDATA) && (myport == mytelport))
connection_status = dumpcon (myport, mywindow);
break;
/* Wait for response from "PORT" command, then send ftp command */
case 2:
if (mycode == CONDATA) {
connection_status = dumpcon (myport, mywindow);
netpush (screens[mywindow].port);
netwrite (screens[mywindow].port, screens[mywindow].ftpbuf, strlen (screens[mywindow].ftpbuf)); /* send command */
screens[mywindow].ftpstate = screens[mywindow].ftpnext;
}
break;
/* Wait for response from "TYPE" command, then send ftp command */
case 3:
if (mycode == CONDATA) {
connection_status = dumpcon (myport, mywindow);
cmd_status = ftpdo (mywindow, screens[mywindow].ftpbuf, "");
}
break;
case 5:
/* Get the next file of an MGET. */
if ((screens[mywindow].clientflags & CAPTURE_DATA) != 0) {
screens[mywindow].clientflags &= ~CAPTURE_DATA;
}
/* After capturing the data, initiate the file transfer(s) */
if ((screens[mywindow].clientflags & MGET_STATE) != 0) {
if (screens[mywindow].capturesize > 0) {
screens[mywindow].ftpstate = 6;
netputuev (CONCLASS, CONDATA, mytelport,0); /* Stay alive to transfer file */
}
else {
screens[mywindow].clientflags &= ~MGET_STATE;
screens[mywindow].ftpstate = 1;
}
}
break;
/* Receive one MGET file. */
case 6:
connection_status = dumpcon (myport, mywindow);
if (getnname ((char *) captlist, (char *) word)) { /* for each name */
#if 0
if (prompt) { /* check */
sprintf (printline, "mget %s? ", word);
putstring (mywindow, printline);
if (ftpgets (answer, 20, 1) == ABORT) { /* abort */
command[0] = '\0'; /* no more processing */
break; /* quit immediately */
}
if (tolower (*(stpblkp (answer))) != 'y')
continue;
}
else {
#endif
sprintf (printline, "Receiving %s\015\013", word);
putstring (mywindow, printline);
#if 0
}
#endif
sprintf (command, "RETR \"%s\"", word);
if ((cmd_status = ftpdo (mywindow, command, "")) < 0) {
screens[mywindow].clientflags &= ~MGET_STATE;
screens[mywindow].ftpstate = 1;
}
}
else {
screens[mywindow].clientflags &= ~MGET_STATE;
screens[mywindow].ftpstate = 1;
}
break;
/* Send a file to the remote connection */
case 20:
if (mycode == CONFAIL)
mycode = CONCLOSE; /* something went wrong */
if (mycode == CONOPEN) {
screens[mywindow].ftpstate = 21;
transtime = TickCount ();
translen = 0;
towrite = 0;
xp = 0;
netputuev (CONCLASS, CONDATA, myport,0);
}
else if ((mycode == CONDATA) && (myport == mytelport)) {
connection_status = dumpcon (myport, mywindow);
}
break;
case 21:
/* transfer file(s) to the other host via ftp request file is already open = ftpfh */
if (mycode == CONDATA) {
if (myport == mytelport) {
connection_status = dumpcon (myport, mywindow);
}
else if (myport == myftpdata) {
netputuev (CONCLASS, CONDATA, myport,0); /* Stay alive */
if (towrite <= xp) {
i = BUFFERS;
towrite = MBread (ftp_mbfp, xs, i);
xp = 0;
}
if ((towrite <= 0) || netest (myftpdata)) {/* we are done */
if (ftp_mbfp->fd != 0)
MBclose (ftp_mbfp); /* BYU - close input file */
screens[mywindow].ftpstate = 22;
break;
}
if (ftpfilemode == FAMODE)
i = Sfwrite (myftpdata, &xs[xp], (int) towrite - xp);
else
i = netwrite (myftpdata, &xs[xp], (int) towrite - xp);
if (i > 0) {
xp += i;
translen += i;
}
mytime = TickCount ();
if ((transtime + 800) < mytime) {
transtime = mytime;
sprintf (printline, "%ld/%ld bytes sent.\015\013", translen, filelen);
i = strlen (printline);
parse (&screens[mywindow], (unsigned char *) &printline[0], i);
}
}
}
break;
case 22: /* wait for data to be accepted */
netputuev (CONCLASS, CONDATA, myport,0); /* Stay alive */
fcnt = netpush (myftpdata); /* will go negative on err */
if (!fcnt || netest (myftpdata)) {
mycode = CONCLOSE;
sprintf (printline, "%ld/%ld bytes sent.\015\013", translen, filelen);
parse (&screens[mywindow], (unsigned char *) &printline[0], strlen (printline));
}
if ((mycode == CONDATA) && (myport == mytelport))
connection_status = dumpcon (myport, mywindow);
break;
/* Get a file from the remote connection */
case 30:
if (mycode == CONFAIL)
mycode = CONCLOSE; /* something went wrong */
if (mycode == CONOPEN) {
screens[mywindow].ftpstate = 31;
filelen = xp = 0;
transtime = TickCount ();
translen = 0L;
}
else if ((mycode == CONDATA) && (myport == mytelport)) {
connection_status = dumpcon (myport, mywindow);
}
break;
/* file has already been opened, take everything from the connection and place into the
open file: ftpfh */
case 31:
if (mycode == CONDATA) {
if (myport == mytelport) {
connection_status = dumpcon (myport, mywindow);
}
else if (myport == myftpdata) {
/* wait until xs is full before writing to disk */
if (filelen <= 2000) {
if (xp) {
if (0 > MBwrite (ftp_mbfp, xs, xp))
mycode = CONCLOSE;
xp = 0;
}
filelen = BUFFERS; /* expected or desired len to go */
}
if (mycode == CONDATA) {
if (ftpfilemode == FAMODE)
fcnt = Sfread (myftpdata, (char *)&xs[xp], (long) filelen);
else
fcnt = netread (myftpdata, &xs[xp], (int) filelen);
if (fcnt >= 0) {
filelen -= fcnt;
xp += fcnt;
translen += fcnt;
}
mytime = TickCount ();
if ((transtime + 800) < mytime) {
transtime = mytime;
if ((screens[mywindow].clientflags & MGET_STATE) == 0) {
sprintf (printline, "%ld bytes received.\015\013", translen);
i = strlen (printline);
parse (&screens[mywindow], (unsigned char *) &printline[0], i);
}
}
/* printf(" %d %d %d \012",filelen,xp,fcnt); n_row(); */
if (fcnt < 0) {
if (0 > MBwrite (ftp_mbfp, xs, xp)) {
break;
}
if (ftp_mbfp->fd != 0) {
MBclose (ftp_mbfp);
}
ftpfh = 0;
}
netputuev (CONCLASS, CONDATA, myport,0);
}
}
}
/* Ouput any remaining data before closing */
if (mycode == CONCLOSE) {
if (xp) {
if (0 > MBwrite (ftp_mbfp, xs, xp))
netclose (myftpdata);
}
if ((screens[mywindow].clientflags & MGET_STATE) == 0) {
sprintf (printline, "%ld bytes received.\015\013", translen);
i = strlen (printline);
parse (&screens[mywindow], (unsigned char *) &printline[0], i);
}
}
break;
/* Waiting for "ftpdata" connection to open, display any communication from the telnet
port. */
case 40:
if (mycode == CONOPEN)
screens[mywindow].ftpstate = 41;
if ((myport == myftpdata) &&
((screens[mywindow].clientflags & CAPTURE_DATA) != 0)) {
captcon (myport, mywindow);
}
else {
connection_status = dumpcon (myport, mywindow);
}
break;
/* If the "ftpdata" port is open, then postpone reading and displaying any data from other
ports once data has been received. Otherwise, read and display data from anywhere. */
case 41:
if (mycode == CONDATA) {
if ((myport == myftpdata) &&
((screens[mywindow].clientflags & CAPTURE_DATA) != 0)) {
captcon (myport, mywindow);
}
else {
connection_status = dumpcon (myport, mywindow);
}
if (myport == myftpdata)
screens[mywindow].ftpstate = 42;
netputuev (CONCLASS, CONDATA, myport,0);
}
else if (mycode == CONCLOSE) {
screens[mywindow].ftpstate = 40;
}
break;
/* Only data from "ftpdata" */
case 42:
if (mycode == CONDATA) {
if (myport == myftpdata) {
if ((screens[mywindow].clientflags & CAPTURE_DATA) != 0) {
captcon (myport, mywindow);
}
else {
connection_status = dumpcon (myport, mywindow);
}
}
netputuev (CONCLASS, CONDATA, myport,0); /* Keep port monitoring alive */
}
else if (mycode == CONCLOSE) {
screens[mywindow].ftpstate = 40;
}
break;
} /* end of switch */
/* After reading from connection, if the connection is closed, reset up shop. */
if ((mycode == CONCLOSE) || (connection_status < 0)) { /* BYU 2.4.12 */
if (connection_status < 0) /* BYU 2.4.12 */
screens[mywindow].clientflags &= ~MPUT_STATE;
if (ftpfh > 0) {
/* Close(ftpfh); /* BYU LSC */
ftpfh = 0;
}
if (ftp_mbfp->fd != 0)
MBclose (ftp_mbfp);
screens[mywindow].ftpstate = 1;
fcnt = 0;
if (myftpdata == myport) {
netclose (myftpdata);
SetPortType(myftpdata, NO_TYPE);
screens[mywindow].ftpport = -1;
}
if ((screens[mywindow].clientflags & TYPE_I_ON_CLOSE) != 0) {
screens[mywindow].clientflags = 0;
cmd_status = ftpdo (mywindow, "TYPE I", "");
}
/* Send the next file of an MPUT */
if ((screens[mywindow].clientflags & MPUT_STATE) != 0) {
needanswer = TRUE;
while (needanswer) {
needanswer = FALSE;
if (glob) { /* local wildcard expansion */
newfile = (unsigned char *) nextname (Template, &ClientDirectoryState); /* get next name */
if (newfile == NULL) { /* if no expansions yet */
if (getword ((char *) captlist, (char *) transfile)) {
strcpy(Template, (char *) transfile);
newfile = (unsigned char *) firstname (Template, TelInfo->FTPClientDirID, TelInfo->FTPClientVRefNum, &ClientDirectoryState); /* get first name */
if (newfile == NULL) { /* if no expansions */
sprintf (printline, "No match for %s", transfile);
ftpclient_debug_print (printline);
}
}
}
}
else if (getword ((char *) captlist, (char *) transfile)) {
newfile = transfile;
}
else
newfile = NULL;
if (newfile == NULL) {
screens[mywindow].clientflags &= ~MPUT_STATE;
screens[mywindow].ftpstate = 1;
}
else {
#if 1 /* When prompting is fixed switch to the
code below */
sprintf (screens[mywindow].ftpbuf, "STOR \"%s\"", newfile);
cmd_status = ftpdo (mywindow, screens[mywindow].ftpbuf, "");
#else
if (prompt) { /* check */
sprintf (printline, "mput %s? ", newfile);
putstring (mywindow, printline);
if (ftpgets (answer, 20, 1) == ABORT) { /* abort */
screens[mywindow].clientflags &= ~MPUT_STATE;
screens[mywindow].ftpstate = 1;
}
else if (tolower (*(stpblkp (answer))) != 'y') {
needanswer = TRUE;
}
else {
sprintf (screens[mywindow].ftpbuf, "STOR \"%s\"", newfile);
cmd_status = ftpdo (mywindow, screens[mywindow].ftpbuf, "");
}
}
else {
/* The Mac file may have special characters, so quote the whole thing */
sprintf (screens[mywindow].ftpbuf, "STOR \"%s\"", newfile);
cmd_status = ftpdo (mywindow, screens[mywindow].ftpbuf, "");
}
#endif
}
}
}
if ((screens[mywindow].clientflags & MGET_STATE) != 0) {
screens[mywindow].ftpstate = 5; /* BYU 3 */
netputuev (CONCLASS, CONDATA, mytelport,0); /* BYU 3 - Stay alive to transfer file */
}
}
return (TRUE);
}